#include <iostream>
#include <string.h>
//疑问：1.为什么一定要定义这个内部类：
//如果不定义这个内部类的话，我们无法分辨出来读和写操作
//无论是 cout << str[0] << endl   还是  str[0] = 'H'读写操作
//返回的都是一个char& 我们无法分辨出它是读操作还是写操作返回的
//但是通过定义一个内部类，返回的是一个CharPoxy对象这样可以重载<<和=来分辨读写操作
using namespace std;
class CowString
{
public:
    CowString()
        : _pstr(new char[1 + 4]() + 4)
    {
    }
    CowString(const char *pstr)
        : _pstr(new char[strlen(pstr) + 4]() + 4)
    {
        strcpy(_pstr, pstr);
        *(int *)(_pstr - 4) = 1;
    }
    // 拷贝构造函数，拷贝需要增加引用计数
    CowString(const CowString &rhs)
        : _pstr(rhs._pstr)
    {
        ++*(int *)(_pstr - 4);
    }
    // 赋值运算符
    CowString &operator=(const CowString &rhs)
    {
        if (this != &rhs)
        {
            if (--*(int *)(_pstr - 4) == 0)
            {
                delete[] (_pstr - 4);
            }
            _pstr = rhs._pstr;
            ++*(int *)(_pstr - 4);
        }
        return *this;
    }
#if 0 
    //这个重载无法区分写操作和读操作
    char &operator[](size_t index)
    {
        if (index >= strlen(_pstr))
        {
            static char nullchar = '\0';
            return nullchar;
        }
        if (*(int *)(_pstr - 4) > 1)
        {
            char *temp = new char[strlen(_pstr) + 1 + 4]() + 4;
            strcpy(temp, _pstr);
            --*(int *)(_pstr - 4);
            _pstr = temp;
            *(int *)(_pstr - 4) = 1;
        }
        return _pstr[index];
    }
    cout << str[0]<<endl
#endif
    ~CowString()
    {
        if (--*(int *)(_pstr - 4) == 0)
        {
            delete[] (_pstr - 4);
        }
    }
    int refcount() const
    {
        return *(int *)(_pstr - 4);
    }
    int size() const
    {
        return strlen(_pstr);
    }
    const char *c_str() const
    {
        return _pstr;
    }

private:
    class CharPoxy
    {
    public:
        CharPoxy(CowString &str, size_t index)
            : _index(index), _str(str)
        {
        }
        friend ostream &operator<<(ostream &os, const CowString::CharPoxy &rhs);
        char &operator=(const char &ch)
        {
            if (_index >= _str.size())
            {
                static char nullchar = '\0';
                return nullchar;
            }
            if (_str._pstr[_index] != ch)
            {
                if (_str.refcount() > 1)
                {
                    char *temp = new char[strlen(_str._pstr) + 1 + 4]() + 4;
                    strcpy(temp, _str._pstr);
                    --*(int *)(_str._pstr - 4);
                    _str._pstr = temp;
                    *(int *)(_str._pstr) = 1;
                }
                // 等于1的时候直接修改值
                _str._pstr[_index] = ch;
            }
            return _str._pstr[_index];
        }

    private:
        size_t _index;
        CowString &_str;
    };

public:
    CharPoxy operator[](size_t index)
    {
        return CharPoxy(*this, index);
    }
    friend ostream &operator<<(ostream &os, const CowString::CharPoxy &rhs);

private:
    char *_pstr;
};
ostream &operator<<(ostream &os, const CowString::CharPoxy &rhs)
{
    if (rhs._index >= rhs._str.size())
    {
        static char nullchar = '\0';
        os << nullchar;
    }
    else
    {
        os << rhs._str._pstr[rhs._index];
    }
    return os;
}
void test()
{
}
int main()
{
    test();
    return 0;
}
